//
// Created by Pulsar on 2021/8/26.
//

#include <rc_task/rcDetectorTask.h>
#include <rc_log/slog.hpp>
#include <dlfcn.h>
#include <rc_task/rcTaskVariable.h>

namespace rccore {
    namespace task {
        DetectorTask::DetectorTask(std::shared_ptr<common::Context> _pcontext) : BaseTask(_pcontext) {

        }

        DetectorTask::~DetectorTask() {

        }

        void DetectorTask::Run() {
            m_thread = new std::thread([=]() {
                slog::info << "检测器任务启动" << slog::endl;
                if (pcontext->pconfig->pconfigInfo->USE_DETCET_PLUGUNS) {
                    std::string detector_library_path = pcontext->pconfig->pconfigInfo->DETCET_PLUGUNS_PATH;
                    void *library_handle;
                    char *handle_error;
                    library_handle = dlopen(detector_library_path.c_str(), RTLD_LAZY);
                    if (!library_handle) {
                        slog::err << "检测器加载失败" << slog::endl;
                        exit(-1);
                    }
                    slog::success << "检测器加载成功" << slog::endl;

                    *(void **) (&this->detect_callback) = dlsym(library_handle, "DetectCallback");
                    if ((handle_error = dlerror()) != NULL) {
                        slog::err << "detect_callback链接失败" << handle_error << slog::endl;
                        exit(-1);
                    }
                    slog::success << "detect_callback链接成功" << slog::endl;

                    *(void **) (&this->after_detecet_callback) = dlsym(library_handle, "AfterDetcetCallback");
                    if ((handle_error = dlerror()) != NULL) {
                        slog::err << "after_detecet_callback 链接失败" << handle_error << slog::endl;
                        exit(-1);
                    }
                    slog::success << "after_detecet_callback 链接成功" << slog::endl;

                    *(void **) (&this->before_detecet_callback) = dlsym(library_handle, "BeforeDetcetCallback");
                    if ((handle_error = dlerror()) != NULL) {
                        slog::err << "before_detecet_callback 链接失败" << handle_error << slog::endl;
                        exit(-1);
                    }
                    slog::success << "before_detecet_callback 链接成功" << slog::endl;

                    *(void **) (&this->on_thread_break_callback) = dlsym(library_handle, "OnThreadBreakCallback");
                    if ((handle_error = dlerror()) != NULL) {
                        slog::err << "on_thread_break_callback 链接失败" << handle_error << slog::endl;
                        exit(-1);
                    }
                    slog::success << "on_thread_break_callback 链接成功" << slog::endl;

                    *(void **) (&this->init_callback) = dlsym(library_handle, "InitCallback");
                    if ((handle_error = dlerror()) != NULL) {
                        slog::err << "init_callback 链接失败" << handle_error << slog::endl;
                        exit(-1);
                    }
                    slog::success << "init_callback 链接成功" << slog::endl;

                    void *args = this->init_callback();
                    task::task_variable::TASK_NUM += 1;
                    while (not m_isStop) {
                        std::unique_lock<std::mutex> m_locker(m_mutex);
                        m_cv.wait(m_locker, [this] { return !m_isPause; });
                        if (not pcontext->pmessage_server->pimageMessage->empty()) {
                            if (not pcontext->pmessage_server->pimageMessage->front_message().empty()) {
                                cv::Mat frame = pcontext->pmessage_server->pimageMessage->front_message().clone();
                                args = this->before_detecet_callback(args);
                                this->detect_callback(frame, args, pcontext->pmessage_server->pmoveMessage);
                                args = this->after_detecet_callback(args);
                                m_locker.unlock();
                            }
                        }
                        std::this_thread::sleep_for(std::chrono::microseconds(30));
                    }
                    this->on_thread_break_callback(args);
                    task::task_variable::TASK_NUM -= 1;
                    dlclose(library_handle);
                } else {
                    task::task_variable::TASK_NUM += 1;
                    while (not m_isStop) {
                        std::unique_lock<std::mutex> m_locker(m_mutex);
                        m_cv.wait(m_locker, [this] { return !m_isPause; });
                        if (not pcontext->pmessage_server->pimageMessage->empty()) {
                            if (not pcontext->pmessage_server->pimageMessage->front_message().empty()) {
                                m_locker.unlock();
                                cv::Mat frame = pcontext->pmessage_server->pimageMessage->front_message().clone();
                                //调试窗口打开
                                if (pcontext->pconfig->pconfigInfo->DEBUG_WINDOW) {
                                    cv::imshow("detector", frame);
                                    cv::waitKey(1);
                                }
                            }
                        }
                        m_locker.unlock();
                        std::this_thread::sleep_for(std::chrono::microseconds(30));
                    }
                    task::task_variable::TASK_NUM -= 1;
                }

                slog::warn << "检测器任务关闭" << slog::endl;
            });
        }
    }
}